package com.wholeintech.wirednet;

import android.content.Context;
import android.content.Intent;
import android.util.Log;

import com.wholeintech.utils.CommonUtil;
import com.wholeintech.entity.DeviceDb;

import org.xutils.DbManager;
import org.xutils.ex.DbException;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.util.Arrays;
import java.util.List;

import static com.wholeintech.utils.ByteUtils.byte2hex;
import static com.wholeintech.zigbee.gw.DeviceManager.TYPE_FLOOR_HEATING;
import static com.wholeintech.zigbee.gw.DeviceManager.TYPE_FRESH_AIR;
import static com.wholeintech.utils.CommonIntent.ACTION_BOX_WIREDNET_TO_ZIGBEE;
import static com.wholeintech.utils.CommonIntent.ACTION_EVENT_AIRRADIO;

public class WrdNetFbProc implements Runnable{

	private final static String TAG = WrdNetFbProc.class.getSimpleName();
	Boolean stop_thread = false;
	public final static int DEV_TYPE_FRESH_AIR = 1070;//新风
	public final static int DEV_TYPE_FLOOR_HEATING = 1060;//地暖
	public final static int DEV_TYPE_NETWORK_SWITCH = 2011;//IP485网关
	public final static String ACTION_UPDATE_UI_DEVICE_STATUS = "com.wit.update.ui.device.status";

	private Context mContext;
	private final static int UDPSERVICE_PORT = 46631;
	private final static int FBDATA_MAX_LEN = 4096;
	private DeviceDb freshAirDb = null;
	private DeviceDb ip485Dev = null;//
	private List<DeviceDb> ip485FloorHeateList = null;
	private DbManager db = null;
	private boolean supportFreshAirPM25 = false;//是否支持新风PM25和CO2
	private boolean supportYiLinFloorHeate = false;//是否支持亿林地暖
	
	public WrdNetFbProc(Context mContext) {
		this.mContext = mContext;
		//根据生成的版本类型，自动开启或关闭某些功能
		loadVersionConfig();

		db = CommonUtil.MyDbUtils();
		try {
			freshAirDb = db.selector(DeviceDb.class).where("type", "=", DEV_TYPE_FRESH_AIR).findFirst();
			if(supportYiLinFloorHeate) {
				//查找所有485网关列表
				List<DeviceDb> ip485devList =  db.selector(DeviceDb.class).where("type", "=", DEV_TYPE_NETWORK_SWITCH).findAll();
				if(ip485devList!=null && ip485devList.size()>0) {
					for (DeviceDb deviceDb : ip485devList) {
						//当终端配置多个485网关时，需要找到挂载地暖的网关
						String str485DevId = deviceDb.getDevId();
						//查询网关下，是否挂载地暖设备(亿林地暖设备)
						ip485FloorHeateList = db.selector(DeviceDb.class)
								.where("gwDevId", "=", str485DevId)
								.and("type", "=", DEV_TYPE_FLOOR_HEATING)
								.findAll();
						if (ip485FloorHeateList != null && ip485FloorHeateList.size() > 0) {
							//找到挂载地暖的485网关，则加载地暖列表，并记录此485网关数据,一个终端只允许一个挂载地暖的485网关
							ip485Dev = deviceDb;
							break;
						}
					}
				}

			}
		}catch (Exception ex){
			ex.printStackTrace();
		}
	}

	/**
	 * 根据生成的版本类型，自动开启或关闭某些功能
	 */
	private void loadVersionConfig(){
		int intVersionType = CommonUtil.getVersionType(mContext);
		if(intVersionType == 2){
			//2.宏云版本(亿林地暖)
			supportYiLinFloorHeate = true;
		}else{
			supportYiLinFloorHeate = false;
		}

		if(intVersionType == 6){
			//6.万科版本(离家不控制窗帘和地暖，不带加湿功能图标，新风为比邻新风定制)
			supportFreshAirPM25 = true;
		}else{
			supportFreshAirPM25 = false;
		}
	}

	@Override
	public void run() {
		int fbDataLen = 0;
		byte[] buffer = new byte[FBDATA_MAX_LEN];
		DatagramPacket udpPacket = new DatagramPacket(buffer, buffer.length);
		DatagramSocket udpSocket = null;
		try {
			udpSocket = new DatagramSocket(UDPSERVICE_PORT);
			
		} catch (SocketException e1) {
			e1.printStackTrace();
		}
		
		while(!stop_thread) {
			try {
				//Log.e(TAG,"===WrdNetFbProc===start read");
				Arrays.fill(buffer, (byte)0);
				
				udpSocket.receive(udpPacket);
				Log.d(TAG, "Recive feedback data1!=="+udpPacket.getData().length);
				//Log.e(TAG,"===WrdNetFbProc===ip:"+udpPacket.getAddress().getHostAddress());
				if (null != udpPacket.getAddress()) {
					//Log.d(TAG, "Recive feedback data1=="+new String(udpPacket.getData(),"UTF-8"));

					if(supportFreshAirPM25) {
						//处理新风上报的空气信息
						handleAirInfo(buffer, udpPacket.getData().length);
					}

					if(supportYiLinFloorHeate) {
						//存在亿林地暖设备时，处理地暖上报的室内温度信息
						handleFloorHeateTemperature(buffer, udpPacket.getData().length);
					}

					for(int i = 0; i < udpPacket.getData().length; i++){
						if(buffer[i] == (byte)0xFC) {
							fbDataLen = fbDataLen + ((buffer[i+1])&0x00ff) + 5;
						}
					}
					
					if((fbDataLen > FBDATA_MAX_LEN) || (fbDataLen <= 0)) {
						//Log.d(TAG, "FB data length error!");
						fbDataLen = 0;
					} else {												//Add by hy,2018/05/02
						byte[] data = new byte[fbDataLen];
						System.arraycopy(buffer, 0, data, 0, data.length);
						//Log.d(TAG, "FB data:" + byte2hex(data));
						fbDataLen = 0;
						//接收到ip/Zigbee转发过来的指令
		                Intent mIntent = new Intent(ACTION_BOX_WIREDNET_TO_ZIGBEE);
		                mIntent.putExtra("wirdtozigbeeData", data);
	
		                Log.i(TAG, "ACTION_BOX_WIREDNET_TO_ZIGBEE" );
		                mContext.sendBroadcast(mIntent);
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 处理地暖上报的温度数据
	 * @param buffer
	 * @param packetLength
	 */
	public void handleFloorHeateTemperature(byte[] buffer,int packetLength){
		if(buffer == null || packetLength == 0)
			return;

		int intStartIndex = 0;
		int intEndIndex = 0;

		for(int i = 0; i < packetLength; i++){
			if(buffer[i] == (byte)0xC7) {
				intStartIndex = i;
			}else if(buffer[i] == (byte)0x7C){
				intEndIndex = i;
			}
		}

		byte[] data = new byte[10];
		if(intEndIndex>0){
			System.arraycopy(buffer, intStartIndex, data, 0, data.length);
			if(data[1] == (byte)0xe3){
				//亿林地暖设备时
				int devIndex = data[2];//获取地暖设备在接在485上的序号
				//=====正式版本
				//int sw = data[3];//开关状态
				//提取温度数据
//				//int temperatureData = (data[4] & 0xff) | ((data[5] << 8) & 0xff00); // | 表示安位或
//				int roomTempData =  (data[3] & 0xff) | ((data[4] << 8) & 0xff00); // | 表示安位或
//				//int temperature =  temperatureData/10;
//				int roomTemp = roomTempData/10;
				//==================================================================================

				//测试版本===========================================================================
				int sw = data[3];//开关状态
				//提取温度数据
				int temperatureData = (data[4] & 0xff) | ((data[5] << 8) & 0xff00); // | 表示安位或
				int roomTempData =  (data[6] & 0xff) | ((data[7] << 8) & 0xff00); // | 表示安位或
				int temperature =  temperatureData/10;
				int roomTemp = roomTempData/10;
				//==================================================================================

				//Log.e(TAG,"==handleFloorHeateTemperature===原始数据:"+byte2hex(data)+"==收到数据==温度:"+temperature+"==第"+devIndex+"路===sw:"+sw+"====roomTemp:"+roomTemp);
				Log.e(TAG,"==handleFloorHeateTemperature===原始数据:"+byte2hex(data)+"==收到数据====第"+devIndex+"路=======roomTemp:"+roomTemp);
				Log.e("FloorHeating","WrdNetFbProc==handleFloorHeateTemperature===原始数据:"+byte2hex(data)+"==收到数据====第"+devIndex+"路=======roomTemp:"+roomTemp+"==temperature:"+temperature+"==sw:"+sw);

				for(DeviceDb deviceDb:ip485FloorHeateList){
					String strDevId = deviceDb.getDevId();
					int devIdEndIndex = Integer.parseInt(strDevId.substring(strDevId.length()-1));

					Log.e(TAG,"=====strDevId:"+strDevId+"=====devIdIndex:"+devIndex);
					Log.e("FloorHeating","WrdNetFbProc=====strDevId:"+strDevId+"=====devIdIndex:"+devIndex);
					if(devIdEndIndex == devIndex){
						//修改指定地暖的温度
						try {
							deviceDb = db.selector(DeviceDb.class)
									.where("devId", "=", deviceDb.getDevId()).findFirst();
							updateFloorHeateDb(deviceDb, temperature,sw,roomTemp);//测试版本
							//updateFloorHeateDb(deviceDb,roomTemp);正式版本
						}catch (Exception ex){
							ex.printStackTrace();
						}
						break;
					}
				}
			}
		}
	}

	/**
	 * 修改地暖温度
	 * @param deviceDb
	 //* @param intTemperature
	 */
	private void updateFloorHeateDb(DeviceDb deviceDb,int intTemperature,int intSw,int intRoomTemp){
		if(deviceDb!=null && db!=null){
			deviceDb.setSetTemp(intTemperature);
			deviceDb.setSw(intSw);
			deviceDb.setTEMP(intRoomTemp);
			try{
				db.saveOrUpdate(deviceDb);
				Intent mIntent = new Intent(ACTION_UPDATE_UI_DEVICE_STATUS);
				mIntent.putExtra("boxId", deviceDb.getBoxId());
				mIntent.putExtra("deviceId", deviceDb.getDevId());
				mIntent.putExtra("network", TYPE_FLOOR_HEATING);
				mIntent.putExtra("temperature",intTemperature);
				mIntent.putExtra("sw",intSw);
				mIntent.putExtra("temp",intRoomTemp);
				mContext.sendBroadcast(mIntent);
				Log.e("FloorHeating","WrdNetFbProc==boxId："+deviceDb.getBoxId()+"==deviceId:"+deviceDb.getDevId()+"==network:"+TYPE_FLOOR_HEATING+"==temperature:"+intTemperature+"==sw:"+intSw+"==temp:"+intRoomTemp);
			}catch (Exception ex){
				ex.printStackTrace();
			}
		}
	}

	//==============================================================================================
	/**
	 * 处理新风上报的空气信息(CO2和PM25)
	 * @param buffer
	 * @param packetLength
	 */
	public void handleAirInfo(byte[] buffer,int packetLength){
		if(buffer == null || packetLength == 0)
			return;

		int intStartIndex = 0;
		int intEndIndex = 0;

		for(int i = 0; i < packetLength; i++){
			if(buffer[i] == (byte)0xC7) {
				intStartIndex = i;
			}else if(buffer[i] == (byte)0x7C){
				intEndIndex = i;
			}
		}

		if(intEndIndex == 0){
			//Log.d(TAG, "FB data length error!");
		}else{
			byte[] data = new byte[4];
			System.arraycopy(buffer, intStartIndex+2, data, 0, intEndIndex-3);
			//获取CO2信息
			int intCo2 = (data[0] & 0xff) | ((data[1] << 8) & 0xff00); // | 表示安位或
			//获取PM25
			int intPm25 = (data[2] & 0xff) | ((data[3] << 8) & 0xff00); // | 表示安位或
			//Log.e(TAG,"=====intCo2==:"+intCo2+"==intPm25:"+intPm25);
			try {
				freshAirDb = db.selector(DeviceDb.class).where("type", "=", DEV_TYPE_FRESH_AIR).findFirst();
				if (freshAirDb != null && db != null) {
					freshAirDb.setPM25(intPm25);
					freshAirDb.setCO2(intCo2);
					try {
						//修改新风设备的PM25和CO2两字段值
						db.saveOrUpdate(freshAirDb);
						//发送广播告知UI,刷新界面
						Intent mIntent = new Intent(ACTION_EVENT_AIRRADIO);
						mIntent.putExtra("boxId", freshAirDb.getBoxId());
						mIntent.putExtra("deviceId", freshAirDb.getDevId());
						mIntent.putExtra("network", TYPE_FRESH_AIR);
						mIntent.putExtra("pm25", intPm25);
						mIntent.putExtra("co2", intCo2);
					} catch (DbException e) {
						e.printStackTrace();
					}
				}

			}catch (Exception ex){
				ex.printStackTrace();
			}
		}
	}
	//==============================================================================================
	public void stop() {
		stop_thread = true;
	}
}
